package com.autumn.mybatis.provider.sqlserver.builder;

import com.autumn.mybatis.metadata.EntityTable;
import com.autumn.mybatis.provider.builder.AbstractQueryBuilder;
import com.autumn.mybatis.provider.sqlserver.AbstractSqlServerProvider;
import com.autumn.mybatis.provider.sqlserver.SqlServerUtils;
import com.autumn.mybatis.provider.util.MybatisSqlUtils;
import com.autumn.util.StringUtils;

/**
 * @author shao
 * @date 2017/11/21 19:24
 */
public abstract class AbstractSqlserverQueryBuilder extends AbstractQueryBuilder {
    /**
     * @param dbProvider
     */
    public AbstractSqlserverQueryBuilder(AbstractSqlServerProvider dbProvider) {
        super(dbProvider);
    }

    /**
     * 锁
     *
     * @param lockModeName
     * @return
     */
    protected static String lockMode(String lockModeName) {
        StringBuilder sql = new StringBuilder();
        sql.append(String.format("<if test=\"%1$s != null \">", lockModeName));
        sql.append("<choose>");
        sql.append(String.format("<when test=\"%1$s.name == 'SHARE'\">", lockModeName));
        sql.append("WITH(HOLDLOCK)");
        sql.append("</when>");
        sql.append(String.format("<when test=\"%1$s.name == 'UPDATE'\">", lockModeName));
        sql.append("WITH(UPDLOCK)");
        sql.append("</when>");
        sql.append("</choose>");
        sql.append("</if>");
        return sql.toString();
    }


    @Override
    public String getSelectByPrimaryKeyByLockSql(EntityTable table, String keyParamName, String lockModeParamName) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ");
        sql.append(MybatisSqlUtils.getAllColumns(table));
        sql.append(" FROM ");
        sql.append(MybatisSqlUtils.getTableOrViewName(table));
        sql.append(lockMode(lockModeParamName));
        sql.append(MybatisSqlUtils.wherePrimaryKeys(table, keyParamName));
        return sql.toString();
    }

    /**
     * 锁查询所有
     *
     * @param table
     * @param lockModeParamName
     * @return
     */
    @Override
    public String getSelectAllLockSql(EntityTable table, String lockModeParamName) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ");
        sql.append(MybatisSqlUtils.getAllColumns(table));
        sql.append(" FROM ");
        sql.append(MybatisSqlUtils.getTableOrViewName(table));
        sql.append(lockMode(lockModeParamName));
        if (!StringUtils.isNullOrBlank(table.getOrderByClause())) {
            sql.append(" ORDER BY ");
            sql.append(table.getOrderByClause());
        }
        return sql.toString();
    }

    /**
     * 获取根据查询全部记录条数的sql（锁）
     *
     * @param table
     * @param lockModeParamName
     * @return
     */
    @Override
    public String getCountByAllLockSql(EntityTable table, String lockModeParamName) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT COUNT(1) FROM ");
        sql.append(MybatisSqlUtils.getTableOrViewName(table));
        sql.append(lockMode(lockModeParamName));
        return sql.toString();
    }

    /**
     * 查询返回一条数据
     * @param table
     *            表
     * @param parmaName
     *            参数名称
     * @return
     */
    @Override
    public String getSelectFirstSql(EntityTable table, String parmaName) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT TOP 1 ");
        sql.append(MybatisSqlUtils.getAllColumns(table));
        sql.append(" FROM ");
        sql.append(MybatisSqlUtils.getTableOrViewName(table));
        sql.append(lockMode(String.format("%s.lockMode", parmaName)));
        sql.append(SqlServerUtils.createSectionWhereSql(parmaName));
        sql.append(getOrder(table));
        return sql.toString();
    }

    /**
     * 根据条件统计
     * @param table
     *            表
     * @param parmaName
     *            参数名称
     * @return
     */
    @Override
    public String getCountByWhereSql(EntityTable table, String parmaName) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT COUNT(*) FROM ");
        sql.append(MybatisSqlUtils.getTableOrViewName(table));
        sql.append(lockMode(String.format("%s.lockMode", parmaName)));
        sql.append(SqlServerUtils.createSectionWhereSql(parmaName));
        return sql.toString();
    }

    /**
     * 生成查询指定列
     *
     * @param parmaName
     * @return
     */
    protected String getSelectBySpecifyBaseSql(String parmaName) {
        StringBuilder sql = new StringBuilder();
        sql.append("<foreach collection=\"" + parmaName + ".selectList\" item=\"item\" separator=\",\">");
        sql.append("${item}");
        sql.append("</foreach>");
        return sql.toString();
    }

    /**
     * 排序
     *
     * @return
     */
    protected String getOrder(EntityTable table) {
        StringBuilder sql = new StringBuilder();
        sql.append("<choose >");
        sql.append("<when test=\"section.orderClauses.size>0\">");
        sql.append("<trim prefix=\"ORDER BY\" suffixOverrides=\",\">");
        sql.append("<foreach collection=\"section.orderClauses\" item=\"item\">");
        sql.append("${item.columnName} ${item.direction}");
        sql.append(",");
        sql.append("</foreach>");
        sql.append("</trim>");
        sql.append("</when>");
        sql.append("<otherwise>");
        sql.append(getPrimaryKey(table));
        sql.append("</otherwise>");
        sql.append("</choose>");
        return sql.toString();
    }

    /**
     * 获取一个主键
     *
     * @param table
     * @return
     */
    private String getPrimaryKey(EntityTable table) {
        //获取第一个主键
        StringBuilder sql = new StringBuilder();
        sql.append("ORDER BY ");
        sql.append(table.getKeyColumns().get(0).getColumnName());
        sql.append(" ASC");
        return sql.toString();
    }
}
